package com.smartfast4j.manager.modules.schedule.service.impl;

import com.smartfast4j.common.Constants;
import com.smartfast4j.common.exception.Smartfast4jException;
import com.smartfast4j.manager.modules.schedule.ScheduleStatus;
import com.smartfast4j.manager.modules.schedule.service.ScheduleJobService;
import com.smartfast4j.manager.modules.schedule.service.ScheduleService;
import com.smartfast4j.mapper.schedule.ScheduleJobMapper;
import com.smartfast4j.pojo.schedule.ScheduleJob;
import com.smartfast4j.pojo.schedule.ScheduleJobExample;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class ScheduleJobServiceImpl implements ScheduleJobService {
    @Autowired
    private ScheduleJobMapper scheduleJobMapper;

    @Autowired
    private ScheduleService scheduleService;

    private static final Logger logger = LoggerFactory.getLogger(ScheduleJobServiceImpl.class);

    public int countByExample(ScheduleJobExample example) {
        int count = this.scheduleJobMapper.countByExample(example);
        logger.debug("count: {}", count);
        return count;
    }

    public ScheduleJob selectByPrimaryKey(Long id) {
        return this.scheduleJobMapper.selectByPrimaryKey(id);
    }

    public List<ScheduleJob> selectByExample(ScheduleJobExample example) {
        return this.scheduleJobMapper.selectByExample(example);
    }

    public int deleteByPrimaryKey(Long id) {
        return this.scheduleJobMapper.deleteByPrimaryKey(id);
    }

    public int updateByPrimaryKeySelective(ScheduleJob record) {
        return this.scheduleJobMapper.updateByPrimaryKeySelective(record);
    }

    public int updateByPrimaryKey(ScheduleJob record) {
        return this.scheduleJobMapper.updateByPrimaryKey(record);
    }

    public int deleteByExample(ScheduleJobExample example) {
        return this.scheduleJobMapper.deleteByExample(example);
    }

    public int updateByExampleSelective(ScheduleJob record, ScheduleJobExample example) {
        return this.scheduleJobMapper.updateByExampleSelective(record, example);
    }

    public int updateByExample(ScheduleJob record, ScheduleJobExample example) {
        return this.scheduleJobMapper.updateByExample(record, example);
    }

    public int insert(ScheduleJob record) {
        return this.scheduleJobMapper.insert(record);
    }

    public int insertSelective(ScheduleJob record) {
        return this.scheduleJobMapper.insertSelective(record);
    }

    public int insertBatchSelective(List<ScheduleJob> records) {
        return this.scheduleJobMapper.insertBatchSelective(records);
    }

    public int updateBatchByPrimaryKeySelective(List<ScheduleJob> records) {
        return this.scheduleJobMapper.updateBatchByPrimaryKeySelective(records);
    }

    @Override
    public ScheduleJob queryByJobName(String jobName){
        if(StringUtils.isEmpty(jobName)){
            return null;
        }
        ScheduleJobExample example = new ScheduleJobExample();
        example.createCriteria().andJobNameEqualTo(jobName);
        List<ScheduleJob> scheduleJobList = selectByExample(example);
        if(CollectionUtils.isNotEmpty(scheduleJobList)){
            return scheduleJobList.get(0);
        }
        return null;
    }

    /**
     * 保存定时任务
     * @param scheduleJob
     */
    @Transactional //涉及到多表操作，开启事务
    @Override
    public void save(ScheduleJob scheduleJob) {
        ScheduleJob existJob = queryByJobName(scheduleJob.getJobName());
        if(existJob != null){
            //抛出自定义异常作为通知，自定义异常会被SpeedTestCloudExceptionHandler捕获处理
            throw new Smartfast4jException("定时任务名称已经存在，请换一个名称！");
        }
        scheduleJob.setCreateTime(new Date());
        scheduleJob.setStatus(ScheduleStatus.NORMAL.getValue());//定时任务状态  0：正常  1：暂停
        insertSelective(scheduleJob);//保存任务
        scheduleService.createJob(scheduleJob);
    }

    /**
     * 更新定时任务
     * @param scheduleJob
     */
    @Transactional //涉及到多表操作，开启事务
    @Override
    public void update(ScheduleJob scheduleJob) {
        ScheduleJob existJob = queryByJobName(scheduleJob.getJobName());
        if(existJob != null){
            if(!existJob.getId().equals(scheduleJob.getId())){
                throw new Smartfast4jException("定时任务名称已经存在，请换一个名称！");
            }
        }
        scheduleService.updateJob(scheduleJob);
        updateByPrimaryKeySelective(scheduleJob);
    }

    @Transactional //涉及到多表操作，开启事务
    @Override
    public void delete(List<Long> jobIds) {
        for(Long jobId:jobIds){
            //删除定时任务
            scheduleService.deleteJob(jobId);
        }
        ScheduleJobExample example = new ScheduleJobExample();
        example.createCriteria().andIdIn(jobIds);
        ScheduleJob scheduleJob = new ScheduleJob();
        scheduleJob.setDeleteFlag(Constants.DELETE_FLAG.YES);
        updateByExampleSelective(scheduleJob,example);//删除定时任务(逻辑删除)
    }

    @Transactional //涉及到多表操作，开启事务
    @Override
    public void run(List<Long> jobIds) {
        ScheduleJobExample example = new ScheduleJobExample();
        example.createCriteria().andIdIn(jobIds);
        List<ScheduleJob> scheduleJobList = selectByExample(example);
        for(ScheduleJob job:scheduleJobList){
            //执行定时任务
            scheduleService.runJob(job);
        }
    }

    @Transactional //涉及到多表操作，开启事务
    @Override
    public void pause(List<Long> jobIds) {
        for(Long jobId:jobIds){
            //暂停定时任务
            scheduleService.pauseJob(jobId);
        }
        //更新任务状态
        updateJobStatus(jobIds,ScheduleStatus.PAUSE.getValue());
    }

    @Transactional //涉及到多表操作，开启事务
    @Override
    public void resume(List<Long> jobIds) {
        for(Long jobId:jobIds){
            //恢复定时任务
            scheduleService.resumeJob(jobId);
        }
        updateJobStatus(jobIds, ScheduleStatus.NORMAL.getValue());
    }

    /**
     * 更新任务状态
     * @param jobIds
     * @param status
     * @return
     */
    private void updateJobStatus(List<Long> jobIds, int status) {
        ScheduleJobExample example = new ScheduleJobExample();
        example.createCriteria().andIdIn(jobIds);
        ScheduleJob scheduleJob = new ScheduleJob();
        scheduleJob.setStatus(status);
        updateByExampleSelective(scheduleJob,example);
    }
}